__author__="Peter"
__date__ ="$Apr 24, 2011 6:18:21 AM$"

## Math Function Library for use with coulomb's laws and portals

##Important imports!
from math import *
from graphics import *
from core_classes import *

##Important constants!

## This is the conversion between pixels and meters, in pixels per meter:
PIX_PER_METER = 1

## This is the conversion from Newtons (m/(s^2)) to Pixtons(pixels/(s^2))
PIXT_PER_NEWTON = PIX_PER_METER

## This will be our version of coulomb's constant:
ELECTROSTATIC_CONSTANT = (8.9875517873681764 * (10**2))/(PIX_PER_METER**2 * PIXT_PER_NEWTON)

def distance(target, source):
    """Returns the distance between two Particles or Charges on a plane"""
    return  sqrt((target.getX()-source.getX())**2 + (target.getY() - source.getY())**2)

def getSingleForceVector(particle, charge):
    """Determines the force on the Particle particle exterted by the Charge
    charge"""

    # First, determine the magnitude of the force
    # compute the distance between the charge and the particle
    dist = distance(particle, charge)
    # compute the magnitude of the force with that
    fMag = (ELECTROSTATIC_CONSTANT * particle.getCharge() * charge.getCharge())/(dist**2)
    # Then, compute the angle between the Force and an the x axis
    # compute the absolute component distance
    dx = (particle.getX() - charge.getX())
    dy = (particle.getY() - charge.getY())
    # compute the angle
    theta = acos((1.0 * dx) / dist)
    # Then, compute the magnitude and direction of the component vectors
    # compute the magnitudes
    xMag = abs(fMag * cos(theta))
    yMag = abs(fMag * sin(theta))
    # compute the directions
    xDir = 0
    yDir = 0
    if dx != 0:
        xDir = (1.0 * dx) / abs(dx)
    if dy != 0:
        yDir = (1.0 * dy) / abs(dy)
    # Finally, swap the directions if the charge is negative and return the ForceVector
    # Swap directions if necessary
    if charge.getCharge() == -1:
        xDir = -xDir
        yDir = -yDir
    # create and return the ForceVector
    return ForceVector(xDir * xMag, yDir * yMag)


def addForceVectors(v1, v2):
    """Returns a ForceVector that is the result of adding the ForceVectors v1
    and v2"""
    return ForceVector(v1.getXComponent()+v2.getXComponent(), v1.getYComponent() + v2.getYComponent())

def getMultipleForceVectors(particle, lst):
    """Returns the composite ForceVector of the forces exerted upon a Particle particle
    by a list of Charges lst"""
    sumVector = ForceVector(0,0)
    for pos in range(len(lst)):
        sumVector = addForceVectors(sumVector, getSingleForceVector(particle,lst[pos]))
    return sumVector


class ForceVector:
    """Responsible for representing a 2-dimensional vector"""

    def __init__(self, xComp, yComp):
        """Creates a ForceVector object from two component vectors, xComp and yComp"""
        self.x = xComp
        self.y = yComp
        self.mag = sqrt(xComp**2 + yComp**2)

    def getXComponent(self):
        """Returns the x component of the ForceVector"""
        return self.x

    def getYComponent(self):
        """Returns the y component of the ForceVector"""
        return self.y

    def getMagnitude(self):
        """Returns the magnitude of the ForceVector"""
        return self.mag